import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import org.jdom.JDOMException;

public class Fuzzer {

	private HashMap<String, String> params ;
	private HashMap<Integer, ArrayList<String>> fuzzTable ;
	private HashMap<Integer, ArrayList<String>> attackTable;
	private ArrayList<String> urls;
	private ArrayList<XssAttack> attackPayload;

	public Fuzzer(Query query) throws IOException, DetectorException, JDOMException{
		this.params = query.getParams();
		this.fuzzTable = FuzzTable.getInstance().getFuzzTable();
		this.attackTable = FuzzTable.getInstance().getAttackTable();
		this.attackPayload = (new CheatSheetBuilder("xssPayloads.txt")).getXssPayloads();
		urls = new ArrayList<String>();
	}

	private String buildQueryStringFromArray(){
		String paramName=null, paramValue = null;
		StringBuilder sb = new StringBuilder();
		Iterator it = params.entrySet().iterator();
		while (it.hasNext()){
			Map.Entry<String,String> currentPair = (Map.Entry<String,String>)it.next();
			paramName = currentPair.getKey();
			paramValue = currentPair.getValue();
			sb.append(paramName + "=" + paramValue + "&");
		}
		sb.deleteCharAt(sb.length()-1);
		return (sb.toString());
	}

	public void buildUrlsList(int num,String mode){
		String paramName=null, queryString=null,newParamVal=null,attackParam=null;
		Iterator<String> it =null;
		int counter=0,rand=0;
		boolean flag = false;
		
		while (counter<=num){
			it = this.params.keySet().iterator();
			while (it.hasNext()){
				paramName = (String)it.next();
				if (mode.equals("reg") && this.fuzzTable.containsKey(paramName.hashCode())){
					flag = true;
					rand = new Random().nextInt(fuzzTable.get(paramName.hashCode()).size());
					newParamVal = fuzzTable.get(paramName.hashCode()).get(rand);
				}
				else if (mode.equals("atk") && this.attackTable.containsKey(paramName.hashCode())){
					flag = true;
					attackParam = paramName;
					//rand = new Random().nextInt(attackTable.size());
					newParamVal = attackTable.get(paramName.hashCode()).get(0);
				}
				else{
					newParamVal = this.params.get(paramName);
				}
				this.params.put(paramName, newParamVal);
			}
			queryString = buildQueryStringFromArray();
			if (!urls.contains(queryString))
				this.urls.add(queryString);
			if (flag==true) 
				counter+=1 ;
			else
				counter=num+1;
		}
		//add all payloads from xss cheatsheet
		if (mode.equals("atk")){
			//sometimes there is a prefix before the actuall payload
			String pfix;
			pfix = attackTable.get(attackParam.hashCode()).get(0);
			int payloadStartIndex = pfix.toLowerCase().indexOf("<script");
			pfix = pfix.substring(0,payloadStartIndex);
			for (XssAttack xa : attackPayload){
				newParamVal = pfix + xa.getPayload();
				this.params.put(attackParam,newParamVal);
				queryString = buildQueryStringFromArray();
				String queryString2 = queryString.replaceAll("\"", "%22");
				queryString2 = queryString2.replaceAll("<", "%3C");
				queryString2 = queryString2.replaceAll(">", "%3E");
				queryString2 = queryString2.replaceAll("\'", "%27");
				if (!urls.contains(queryString)){
					this.urls.add(queryString);
					this.urls.add(queryString2);
				}
			}
		}
	}

	public ArrayList<String> getUrls() {
		return urls;
	}

	/*public static void main(String[] args) {
		URL u= null;
		int c = 1;
		try {
			BufferedReader br = new BufferedReader(new FileReader("xss_sites.txt"));
			BufferedWriter bw = new BufferedWriter(new FileWriter("attackUrls.txt"));
			String current = br.readLine();
			while(current!=null){
				Query query = new Query(current);
				Fuzzer fuzzer = new Fuzzer(query);
				fuzzer.buildRegularUrlList(3);
				for (String url : fuzzer.getUrls()){
					bw.write(c + ") " + url + "\r\n");
					c+=1;
				}
				current = br.readLine();
			}
			bw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DetectorException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}*/

}
